<?php
/**
 * This file houses the View class.
 *
 * Copyright (c) 2010, Kalkomey Enterprises, Inc.
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 * 
 * - Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice, this 
 *   list of conditions and the following disclaimer in the documentation and/or other
 *   materials provided with the distribution.
 * - Neither the name of the Kalkomey Enterprises, Inc. nor the names of its 
 *   contributors may be used to endorse or promote products derived from this 
 *   software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
 * @copyright Copyright (c) 2010, Kalkomey Enterprises, Inc.
 * @link http://code.google.com/p/swerv/
 * @package	Shared
 * @subpackage Protocols_Output
 */

/**
 * The View class is used to pass variables from the output protocol to a view template and build the resulting view.
 *
 * @package	Shared
 * @subpackage Protocols_Output
 */
class View
{

	/**
	 * Container for variables that should be available in the layout and view.
	 * 
	 * @var array
	 */
	private $vars;
	
	/**
	 * The filename of the file to use as the view.
	 * 
	 * @var string
	 */
	private $viewFile;
	
	/**
	 * The filename of the file to use as the layout. Defaults to Default.layout.php
	 * 
	 * @var string
	 */
	private $layout;
	
	/**
	 * If set to true, then the view will not be inserted into a layout.
	 * 
	 * @var bool
	 */
	private $noLayout;
	
	/**
	 * Object constructor.
	 * 
	 * @return View
	 */
	public function __construct($viewFile = '', $layout = 'Default.layout.php', $noLayout = false) {
		$this->vars = array();
		$this->viewFile = $viewFile;
		$this->layout = $layout;
		$this->nolayout = $noLayout;
	}
	
	/**
	 * Sets the filename for the current view.
	 * 
	 * @param string $viewFile
	 * 
	 * @return void
	 */
	public function setView($viewFile) {
		$this->viewFile = $viewFile;
	}
	
	/**
	 * Sets the filename for the current layout.
	 * 
	 * @param string $layoutFile
	 * 
	 * @return void
	 */
	public function setLayout($layoutFile) {
		$this->layout = $layoutFile;
	}

	/**
	 * Sets a variable that should be available in the view.
	 * 
	 * @param string $name
	 * @param mixed $value
	 * 
	 * @return mixed
	 */
	public function setVar($name, $value) {
		$oldValue = null;
		if (array_key_exists($name, $this->vars)) {
			$oldValue = $this->vars[$name];
		}
		$this->vars[$name] = $value;
		return $oldValue;
	}
	
	/**
	 * If called, then the view will not be inserted into the layout.
	 * 
	 * @return void
	 */
	public function noLayout() {
		$this->noLayout = true;
	}
	
	/**
	 * Renders the view and returns it.
	 *
	 * @throws Exception if the view or layout files are missing. 
	 *
	 * @return string
	 */
	public function render() {
		global $paths;
		
		// first we bring in the set variables into the local scope
		extract($this->vars, EXTR_OVERWRITE);

		// possible locations of our files
		$appPath = $paths['app']['protocols'] . '/doc/templates/';
		$sharedPath = $paths['shared']['protocols'] . '/doc/templates/';

		// now we include the view and store it in a variable
		ob_start();
		
		if (file_exists($appPath . $this->viewFile)) {
			include($appPath . $this->viewFile);
		} else if (file_exists($sharedPath . $this->viewFile)) {
			include($sharedPath . $this->viewFile);
		} else {
			throw new Exception('Cannot locate view file "' . $this->viewFile . '".');
		}
		$view = ob_get_clean();
		
		// now we include the layout and store that in a variable; to insert the view into the layout, we simply echo the $view variable since it is in scope
		if (!$this->noLayout) {
			ob_start();
			if (file_exists($appPath . $this->layout)) {
				include($appPath . $this->layout);
			} else if (file_exists($sharedPath . $this->layout)) {
				include($sharedPath . $this->layout);
			} else {
				throw new Exception('Cannot locate layout file "' . $this->layout . '".');
			}
			$layout = ob_get_clean();
		} else {
			$layout = $view;
		}
		return $layout;
	}
}
